package com.wxl.micro.service.gateway.filters;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.support.GatewayToStringStyler;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

/**
 * 自定义局部过滤器
 * 过滤器解决：加一点东西、减一点东西、改一点东西
 *
 * 自定义的规则和断言差不多：
 * 继承AbstractNameValueGatewayFilterFactory且我们的自定义名称必须要以GatewayFilterFactory结尾并交给spring管理
 *
 */

@Component
public class AddTidGatewayFilterFactory extends AbstractGatewayFilterFactory<AddTidGatewayFilterFactory.Config> {

    private static final Log log = LogFactory.getLog(AddTidGatewayFilterFactory.class);
    public static final String TID_KEY = "tid";


    public AddTidGatewayFilterFactory() {
        super(AddTidGatewayFilterFactory.Config.class);
    }

    public List<String> shortcutFieldOrder() {
        return Arrays.asList(TID_KEY);
    }

    public GatewayFilter apply(AddTidGatewayFilterFactory.Config config) {
        return new GatewayFilter() {
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                String tid = UUID.randomUUID().toString();
                ServerHttpRequest request = exchange.getRequest().mutate().header(config.tid, new String[]{tid}).build();
                return chain.filter(exchange.mutate().request(request).build());
            }

            public String toString() {
                return GatewayToStringStyler.filterToStringCreator(AddTidGatewayFilterFactory.this).append(TID_KEY, config.tid).toString();
            }
        };
    }


    public static class Config {
        private String tid;

        public Config() {
        }

        public String getTid() {
            return tid;
        }

        public void setTid(String tid) {
            this.tid = tid;
        }
    }
}
